package com.telra.app.gui;

import java.util.Map;
import java.util.TreeMap;

import javax.jms.Connection;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.Topic;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;

import com.telra.app.server.data.OrderAggregate;
import com.telra.app.server.data.OrderEvent;
import com.telra.app.server.protobuff.AggProtos.AggGUIUpdate;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.Log4JLogger;


public class Desktop {

    private static final Log4JLogger log = (Log4JLogger) LogFactory.getFactory().getInstance(Desktop.class);

    private MyTableModel tm;

    public Desktop() {

        JFrame frame = new JFrame("Order Blotter");
        tm = new MyTableModel();
        JTable table = new JTable(tm);

        frame.add(new JScrollPane(table));

        frame.setSize(600, 400);
        frame.setVisible(true);

        Thread brokerThread = new Thread(new ListenerThread());
        brokerThread.setName("gui listener");
        brokerThread.start();
    }

    private class ListenerThread implements Runnable, ExceptionListener {

        public void run() {

            try {
                // Create a ConnectionFactory
                ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");

                // Create a Connection
                Connection connection = connectionFactory.createConnection();
                connection.start();

                connection.setExceptionListener(this);

                // Create a Session
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

                // Create the destination (Topic or Queue)
                Topic topic = session.createTopic("AGG.OUT");

                // Create a MessageConsumer from the Session to the Topic or Queue
                MessageConsumer consumer = session.createConsumer(topic);

                log.info("started gui listener");


                while (true) {
                    Message message = consumer.receive(5000);	//wait 5 seconds

                    if (message instanceof ObjectMessage) {
                        ObjectMessage bMessage = (ObjectMessage) message;

                        final AggGUIUpdate aggupdate = (AggGUIUpdate)bMessage.getObject();
                        log.info("gui update received");

                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                tm.update(aggupdate);
                            }
                        });


                    }
                }

            } catch (Exception e) {
                log.error("Caught: " + e);
                e.printStackTrace();
            }
        }

        public void onException(JMSException arg0) {
            // TODO Auto-generated method stub

        }

    }

    @SuppressWarnings("serial")
    private class MyTableModel extends AbstractTableModel {

        String[] colName = {"Category", "Count", "Sum", "Avg", "Max"};
        Class<?>[] clazz = {String.class, Integer.class, Double.class, Double.class, Double.class};
        Map<String, OrderAggregate> map = new TreeMap<String, OrderAggregate>();

        public Class<?> getColumnClass(int arg0) {
            return clazz[arg0];
        }

        public int getColumnCount() {
            return colName.length;
        }

        public String getColumnName(int arg0) {
            return colName[arg0];
        }

        public int getRowCount() {
            return map.size();
        }

        public void update(AggGUIUpdate aggupdate) {

            String cat = aggupdate.getItemCategory().toString();
            OrderAggregate old = map.get(cat);
            if (old == null) {
                //convert to the enum
                OrderEvent.Category enumCat = cat.equals("CLOTHING") ? OrderEvent.Category.CLOTHING :
                        cat.equals("ACCESSORIES") ? OrderEvent.Category.ACCESSORIES :
                                cat.equals("FOOTWEAR") ? OrderEvent.Category.FOOTWEAR:
                                        cat.equals("OUTERWEAR") ? OrderEvent.Category.OUTERWEAR:
                                                OrderEvent.Category.MISC;

                old = new OrderAggregate(enumCat, 0 , 0.0, 0.0, 0.0);
                map.put(cat, old);
                this.fireTableStructureChanged();
            }

            old.setCount(aggupdate.getCount());
            old.setAvg(aggupdate.getAvg());
            old.setMax(aggupdate.getMax());
            old.setSum(aggupdate.getSum());
            this.fireTableDataChanged();

        }

        public Object getValueAt(int arg0, int arg1) {
            OrderAggregate agg = (OrderAggregate) map.values().toArray()[arg0];
            switch (arg1) {
                case 0:
                    return agg.getCategory().toString();
                case 1:
                    return agg.getCount();
                case 2:
                    return agg.getSum();
                case 3:
                    return agg.getAvg();
                case 4:
                    return agg.getMax();
            }
            return null;
        }

        public boolean isCellEditable(int arg0, int arg1) {
            return false;
        }

    }

    public static void main(String[] args) {
        new Desktop();
    }

}
